package com.kurumi.autoprint.service.impl;

import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.kurumi.autoprint.datasource.TargetDataSource;
import com.kurumi.autoprint.enums.ResponseStatusEnum;
import com.kurumi.autoprint.mapper.MessageItemsMapper;
import com.kurumi.autoprint.mapper.MessageLogMapper;
import com.kurumi.autoprint.mapper.MrBasicMapper;
import com.kurumi.autoprint.mapper.MrPrintDetailMapper;
import com.kurumi.autoprint.mapper.MrPrintTypeMapper;
import com.kurumi.autoprint.mapper.MrRecordImageMapper;
import com.kurumi.autoprint.pojo.MessageItems;
import com.kurumi.autoprint.pojo.MessageLog;
import com.kurumi.autoprint.pojo.MrBasic;
import com.kurumi.autoprint.pojo.MrPageType;
import com.kurumi.autoprint.pojo.MrPrintDetail;
import com.kurumi.autoprint.pojo.MrPrintDto;
import com.kurumi.autoprint.pojo.MrPrintType;
import com.kurumi.autoprint.pojo.MrRecordImage;
import com.kurumi.autoprint.pojo.ReportFile;
import com.kurumi.autoprint.service.MedRecordService;
import com.kurumi.autoprint.service.WebService;
import com.kurumi.autoprint.util.DateUtil;
import com.kurumi.autoprint.util.FileUtil;
import com.kurumi.autoprint.util.MD5;
import com.kurumi.autoprint.util.PDFAndBase64ConvertUtil;
import com.kurumi.autoprint.util.PDFUtil;
import com.kurumi.autoprint.util.PdfWaterMarkUtil;
import com.kurumi.autoprint.util.Result;
import com.kurumi.autoprint.util.StringUtil;
import com.kurumi.autoprint.util.WaterMarkPosition;

@Service
public class MedRecordServiceImpl implements MedRecordService {
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private MrBasicMapper mrBasicMapper;
	
	@Autowired
	private MrRecordImageMapper mrRecordImageMapper;
	
	@Autowired
	private MessageItemsMapper messageItemsMapper;
	
	@Autowired
	private MessageLogMapper messageLogMapper;
	
	@Autowired
	private MrPrintTypeMapper mrPrintTypeMapper;
	
	@Autowired
	private WebService webService;
	
	@Autowired
	private MrPrintDetailMapper mrPrintDetailMapper;
	
	@Value("${water.mark.fontsize}")
	private String waterMarkFontSize;
	
	/**
	 * webservice url 路径
	 */
	@Value("${webservice.getInpatientRecordsByIdNo.url}")
	private String webServiceUrl;
	/**
	 * webservice获取文件信息方法
	 */
	@Value("${webservice.getReportFile.method}")
	private String reportFileMethod;
	
	@Value("${PRINT_FILR_DIR}")
	private String printFilrDir;
	
	@Value("${print.host.url}")
	private String printHostUrl;
	
	
	@Value("${hospital.name}")
	private String hospitalName;
	
	

	@Transactional(readOnly = true)
	@TargetDataSource(name="ds1")
	@Override
	public List<MrBasic> getMrBasicByIdCard(String idCard,String arcStatus) {
		
		return mrBasicMapper.selectMrBasicByIdCard(idCard,arcStatus);
	}

	@Transactional(readOnly = true)
	@TargetDataSource(name="ds1")
	@Override
	public List<MrRecordImage> getMrRecordImageByOnlyId(String onlyId) {
		
		return mrRecordImageMapper.getMrRecordImageByMrBasicId(onlyId);
	}

	@Transactional(readOnly = true)
	@TargetDataSource(name="ds2")
	@Override
	public int sendMessage(String phone,String code) {
		MessageItems items = new MessageItems();
		items.setMessageId(StringUtil.getId());
		items.setAimTel(phone);
		items.setMessageTxt("验证码:"+code+",有效期为3分钟，请妥善保管您的验证码，请勿将验证码泄露给他人!");
		items.setTypeId("19");
		items.setTxttype("1");	
		items.setCreateDate(new Date());
		return messageItemsMapper.insert(items);
	}

	
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public int addMessageLog(String idCard, String phone, String randomNum) {
		MessageLog messageLog = new MessageLog();
		messageLog.setIdCard(idCard);
		messageLog.setMobile(phone);
		messageLog.setMessageCode(randomNum);
		messageLog.setRecordTime(new Date());
		return messageLogMapper.insertSelective(messageLog);
	}

	@Transactional(readOnly = true)
	@Override
	public boolean validateMessageCode(String idCard, String phone, String messageCod) {
		List<MessageLog> messageLogList = messageLogMapper.getMessageLogByIdCardPhoneCode(messageCod, phone, idCard);
		//根据条件查询数据为空,校验失败
		if(CollectionUtils.isEmpty(messageLogList)) {
			return false;
		}
		//获取最新一条相关数据记录时间和当前时间进行比较
		MessageLog messageLog = messageLogList.get(0);
		if(messageLog!=null && messageLog.getRecordTime()!=null) {
			long beforeTime = messageLog.getRecordTime().getTime();
			long afterTime = new Date().getTime();
			long diff=afterTime-beforeTime;
			long minute1 = diff / 3600 / 60;
			if(minute1<=3) {
				return true;
			}
		}
		return false;
	}
	
	@TargetDataSource(name = "ds1")
	@Transactional(readOnly = true)
	@Override
	public List<MrPrintType> getPrintTypes() {

		return mrPrintTypeMapper.getAllPrintType();
	}
	
	
	
	@Transactional(readOnly=true)
	@TargetDataSource(name = "ds1")
	@Override
	public MrPrintDto getPrintFeeAndPrintPath(String mrBasicId, String printType, Integer printNum,
			String printPieceFee, String ipAddress) throws Exception {
		MrPrintDto mrPrintDto = new MrPrintDto();
		String filePath = null;
		String fileName = null;
		String convertPdfFilePath = null;
		ReportFile reportFile = null;
		String base64PDf = null;
		String folder = DateUtil.dateFormat("yyyy-MM-dd", new Date());
		
		File folderDir = new File(printFilrDir +folder+"/");
		
		if(!folderDir.exists()) {
			folderDir.mkdirs();
		}
		
		//查询是否有当天生成的数据，如果有直接取数据，没有重新生成
		String targetFileName = folder+"/"+MD5.md5(mrBasicId+printType)+".pdf";
		File pdfFile = null;
		pdfFile = new  File(printFilrDir+targetFileName);
		
		if(!pdfFile.exists()) {
			// 保存转化的病案PDF文件
			List<String> covertPdfFileList = new LinkedList<String>();
			// 第一步:根据唯一标识查询本次住院的文件信息
			List<MrRecordImage> mrRecordImages = mrRecordImageMapper.getMrRecordImageByMrBasicId(mrBasicId);
			logger.info("根据唯一标识{}获取住院文件信息成功!文件数量" + mrRecordImages.size(),mrBasicId);
			if (CollectionUtils.isEmpty(mrRecordImages)) {
				return null;
			}

			// 第二步:根据打印类型去打印字典中寻找那些需要打印的单子类型
			List<MrPageType> mrPageTypes = mrPrintTypeMapper.getMrPageByType(printType);
			// 第四步:组合打印类型code集合，方便过滤数据
			List<String> mrPageCodeList = new ArrayList<>();
			for (MrPageType mrPageType : mrPageTypes) {
				if(StringUtils.isNotEmpty(mrPageType.getCode1())) {
					mrPageCodeList.add(mrPageType.getCode1().trim());
				}
				
			}
			// 第五步:循环病案文件信息，过滤掉不在打印类型code中文件
			for (MrRecordImage mrRecordImage : mrRecordImages) {
				if (!mrPageCodeList.contains(mrRecordImage.getMrTypeCode())) {
					continue;
				}

				filePath = mrRecordImage.getHttpUrl();
				fileName = mrRecordImage.getImageUrl();
				if (StringUtils.isEmpty(filePath) || StringUtils.isEmpty(fileName)) {
					continue;
				}

				reportFile = webService.getReportFile(webServiceUrl, reportFileMethod, filePath + fileName + ".pdf");
				if (reportFile == null) {
					continue;
				}

				base64PDf = reportFile.getStream();
				if (StringUtils.isEmpty(base64PDf)) {
					continue;
				}

				convertPdfFilePath = printFilrDir +folder+"/"+StringUtil.getFileName() + ".pdf";
				try {
					boolean flag = PDFAndBase64ConvertUtil.base64StringToPDF(base64PDf, new File(convertPdfFilePath));
					if (flag) {
						covertPdfFileList.add(convertPdfFilePath);
					}
				} catch(Exception e) {
					logger.error("唯一标识为{}的"+mrRecordImage.getMrTypeName()+"PDFbase64二进制转化为PDF文件失败!错误信息为{}",mrBasicId,e.getMessage());
					e.printStackTrace();
				}
			}

			// 第六步:合并由base64位转化的PDF文档
			if (CollectionUtils.isEmpty(covertPdfFileList)) {
				return null;
			}


			String[] array = new String[covertPdfFileList.size()];
			array = covertPdfFileList.toArray(array);
			try {
				String target = printFilrDir + targetFileName;
				PDFUtil.mergePdfFiles(array, target);
				
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("唯一标识为{}合并PDF文件失败!异常信息{}",mrBasicId,e.getMessage());
			}
			
			
			pdfFile =new  File(printFilrDir + targetFileName);
		}
		
		if (pdfFile.exists()) {
			try {
				// 计算一份有多少页
				int pageCount = PDFUtil.getPDFPages(printFilrDir + targetFileName);

				BigDecimal pieceFee = new BigDecimal(printPieceFee);
				BigDecimal printNumDecimal = new BigDecimal(printNum.intValue());
				BigDecimal pageNumDecimal = new BigDecimal(pageCount);
				// 打印份数
				mrPrintDto.setPrintNum(printNum);
				// 打印单价(单位:角)
				mrPrintDto.setSinglePieceFee(pieceFee);
				// 打印总页数
				mrPrintDto.setTotalPrintPage(printNum.intValue() * pageCount);
				// 打印费用
				mrPrintDto.setPrintTotalFee(pieceFee.multiply(pageNumDecimal).multiply(printNumDecimal));
				// PDFbase64位二进制编码
				//mrPrintDto.setPrintPDFbase64(PDFAndBase64ConvertUtil.pdfToBase64(pdfFile));
			} catch (Exception e) {
				logger.error("唯一标识为{},PDF文件路径为{}转化为base64二进制编码错误!错误信息{}",mrBasicId,printFilrDir + targetFileName,e.getMessage());
				e.printStackTrace();
				
				return null;
			}

		} else {
			return null;
		}
		
		return mrPrintDto;

	}
	
	

	/**
	 * 保存打印详情信息
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void addMrPrintDetail(MrPrintDetail mrPrintDetail) {
		mrPrintDetail.setCreateTime(new Date());
		mrPrintDetailMapper.insertSelective(mrPrintDetail);
	}


	/**
	 * 将打印PDF转化为base64二进制编码
	 */
	@Override
	public Result convertPDF2Base64(String mrBasicId, String printTypeCode, String ipAddress) {
		String filePath = null;
		byte[] bytes = null;
		
		try {
			String folder = DateUtil.dateFormat("yyyy-MM-dd", new Date());
			filePath = folder+"/"+MD5.md5(mrBasicId+printTypeCode)+".PDF";
			bytes = this.createPrintMedicalPdfWater(folder + filePath, hospitalName, 
						 ipAddress);
			String base64Str = PDFAndBase64ConvertUtil.ByteArrayToBase64(bytes);
			
			
			
			
			
			return new Result(true,"base64二进制生成成功!",base64Str);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("唯一标示为{},打印类型为{},PDF文件路径为{}PDF转base64失败!错误信息:{}",mrBasicId,printTypeCode,printFilrDir+filePath,e.getMessage());
			return new Result(false,"唯一标识"+mrBasicId+"PDF转base64失败,错误信息"+e.getMessage()+"",ResponseStatusEnum.PDF_TRANSFER_ERROR.getValue());
		} finally {
			bytes = null;
		}
		
	}
	
	/**
	 * 将打印PDF转化为base64二进制编码
	 */
	@Override
	public Result convertPDF2Imgs(String mrBasicId, String printTypeCode, String ipAddress) {
		String filePath = null;
		String waterMarkFilePath = null;
		byte[] bytes = null;
		//存放生成图片地址
		List<String> pngFileNameList =  new LinkedList<String>();
		List<String> printUtlList = new LinkedList<String>();
		
		try {
			String folder = DateUtil.dateFormat("yyyy-MM-dd", new Date());
			filePath = folder+"/"+MD5.md5(mrBasicId+printTypeCode)+".PDF";
			
			
			bytes = this.createPrintMedicalPdfWater(printFilrDir + filePath, hospitalName, 
						 ipAddress);
			
			/*bytes = this.createPrintMedicalPdfWater("D://publics/print/c84ea8d3dde7130386098a18d0f2759d.PDF", hospitalName, 
								 ipAddress);*/
			
			waterMarkFilePath = folder+"/"+mrBasicId+"/";
			
			String waterFilePDFName =StringUtil.getFileName()+".PDF";
			
			//String base64Str = PDFAndBase64ConvertUtil.ByteArrayToBase64(bytes);
			File fileFolder = new File(printFilrDir+waterMarkFilePath);
			if(!fileFolder.exists()) {
				fileFolder.mkdirs();
			}
			
			File file = new File(printFilrDir+waterMarkFilePath+waterFilePDFName);
			try {
				PDFAndBase64ConvertUtil.bytesToPDF(bytes, file);
			} catch (Exception e) {
				e.printStackTrace();
				return new Result(false,"生成水印PDF文件失败",e.getMessage(),500);
			}
			
			try {
				pngFileNameList=PDFUtil.pdf2Img(printFilrDir+waterMarkFilePath+waterFilePDFName, printFilrDir+waterMarkFilePath);
				if(CollectionUtils.isEmpty(pngFileNameList)) {
					return new Result(false,"生成水印图片个数为0",null,200);
				}
				
				for (String pngFileName : pngFileNameList) {
					printUtlList.add(printHostUrl+waterMarkFilePath+pngFileName);
				
				}
				for (String string : printUtlList) {
					System.out.println(string);
				}
				
				pngFileNameList=null;
				
				return new Result(true,"生成水印图片成功!",printUtlList,200);
			} catch (Exception e) {
				e.printStackTrace();
				return new Result(false,"PDF转化为图片文件失败!",e.getMessage(),500);
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("唯一标示为{},打印类型为{},PDF文件路径为{}PDF转base64失败!错误信息:{}",mrBasicId,printTypeCode,printFilrDir+filePath,e.getMessage());
			return new Result(false,"唯一标识"+mrBasicId+"PDF转base64失败,错误信息"+e.getMessage()+"",ResponseStatusEnum.PDF_TRANSFER_ERROR.getValue());
		} finally {
			bytes = null;
		}
		
	}
	
	

	@Override
	public byte[] createPrintMedicalPdfWater(String sourcefilePath, String hospitalName, String ipAddress) throws Exception{
		hospitalName = new String(hospitalName.getBytes("ISO8859-1"),"UTF-8");
		byte[] bytes = PdfWaterMarkUtil.getPdfMarkByText(FileUtil.toByteArray(sourcefilePath), hospitalName, null, 
				 Integer.parseInt(waterMarkFontSize), WaterMarkPosition.LEFT_BUTTOM, 100, 600, -45);
		
		//姓名
		//b = getPdfMarkByText(b, patientName, null, 16, WaterMarkPosition.LEFT_BUTTOM, 350, 70, 0);
		String createTimeFormat = DateUtil.dateFormat(DateUtil.DATE_TIME_FORMATE, new Date());
		
		//创建日期
		bytes = PdfWaterMarkUtil.getPdfMarkByText(bytes, createTimeFormat, null, 16, WaterMarkPosition.LEFT_BUTTOM, 350, 50, 0);
		
		//ip
		if (StringUtils.isNotBlank(ipAddress)) {
			bytes = PdfWaterMarkUtil.getPdfMarkByText(bytes, ipAddress, null, 16, WaterMarkPosition.LEFT_BUTTOM, 350, 30, 0);
		}
		
		return bytes;
	}
	
	
	
	
	
	
	
}
